Load packages

library(tidyverse)
library(gridExtra)
library(cowplot)
library(ggridges)
library(ggstance)
library(treeio)
library(ggtree)
library(tidytree)

Load and combine data

species <- read_csv("../data/species_data.csv") %>% select(-species)
data <- read_csv("../data/data.csv") %>% 
  left_join(species, by = c("species" = "species_formatted")) %>% 
  rename(label = species_latin)
data2 <- data %>% group_by(species, label) %>% summarise(n = sum(n))
fulltree <- read.nexus("../data/consensusTree_10kTrees_298Primates_V3.nex")
refs <- read_csv("../data/ref_nodes.csv")
# turn tree into tidy dataframe
tree2 <- as_tibble(fulltree)

tree3 <- tree2 %>% 
  left_join(data2) %>% 
  mutate(
    hasN = ifelse(is.na(n), 0, .5),
    hasN2 = ifelse(is.na(n), .1, .5)) %>% 
  left_join(refs) %>% 
  # # also merge w datasheet listing node, n for inner nodes
  # left_join(Ns, by = "node") %>% 
  # mutate(n = coalesce(n.x, n.y)) %>% 
  # select(-n.x, -n.y) %>% 
  groupClade(c(493, 496, 429, 302, 408)) %>% 
  mutate(group = fct_recode(group, "2" = "1"))
Joining, by = "label"
Joining, by = "node"
# turn back into tree
tree4 <- as.treedata(tree3)

Figure out nodes

This makes a rectangular and a circular tree with the node numbers displayed for reference (saved in the graphs folder).

tree3.2 <- as.treedata(tree3)
# display node numbers for reference
ggtree(tree3.2) +
  # tip labels
  geom_tippoint(aes(size = n), col = "seagreen", alpha = .5) +
  geom_tiplab(offset = 1, size = 3) +
  # node labels
  geom_text(aes(label = node, x = branch), size = 2, col = "blue", vjust = -.5) +
  expand_limits(x = 90) +
  # display timescale at the bottom
  theme_tree2()
ggsave("../graphs/full_tree_nodes.pdf", width = 8, height = 20, scale = 2)
ggtree(tree3.2, layout = "circular") +
  geom_tippoint(aes(size = n), col = "seagreen", alpha = .5) +
  geom_tiplab2(offset = 2, size = 3) +
  geom_text2(aes(label = node), size = 1.5, col = "blue") +
  xlim(NA, 100)
ggsave("../graphs/full_tree_nodes_circular.pdf", width = 8, height = 8, scale = 2)

Circular tree of 298 primates

cols <- viridis::viridis(4, end = .9)
# base plot
p <- ggtree(tree4, aes(size = hasN, alpha = hasN2), layout = "circular") +
  # root
  geom_rootpoint(size = 1) +
  # tips
  geom_tippoint(aes(size = n), alpha = .5) +
  geom_tiplab2(aes(alpha = hasN), offset = 2, size = 3) +
  # tweak scales
  scale_alpha_continuous(range = c(.3, 1)) +
  scale_size_continuous(range = c(.5, 8)) +
  # widen plotting area
  xlim(NA, 100)
# highlight clades with background colors
p2 <- p + 
  geom_hilight(node = 493, fill = cols[1], alpha = .3) +
  geom_hilight(node = 496, fill = cols[1], alpha = .3) +
  geom_hilight(node = 429, fill = cols[2], alpha = .3) +
  geom_hilight(node = 303, fill = cols[3], alpha = .3) +
  geom_hilight(node = 408, fill = cols[4], alpha = .3) +
  # plot tree again to be on top of the highlights
  geom_tree() +
  geom_rootpoint(size = 1)
# highlight clades with branch colors
p3 <- p + 
  aes(col = group) +
  scale_color_manual(values = c("gray30", cols))
plots <- mget(c("p", "p2", "p3"))
grid.arrange(p, p2, p3, nrow = 1)

# png with 3x1
ggsave("../graphs/phylo_full.png", arrangeGrob(grobs = plots, nrow = 1), 
       width = 24, height = 8, scale = 2, dpi = 72)
Removed 287 rows containing missing values (geom_point_g_gtree).Removed 287 rows containing missing values (geom_point_g_gtree).Removed 287 rows containing missing values (geom_point_g_gtree).
# pdf with 1 per page
ggsave("../graphs/phylo_full.pdf", marrangeGrob(grobs = plots, nrow = 1, ncol = 1), 
       width = 8, height = 8, scale = 2, dpi = 72)
Removed 287 rows containing missing values (geom_point_g_gtree).Removed 287 rows containing missing values (geom_point_g_gtree).Removed 287 rows containing missing values (geom_point_g_gtree).

Sample size in detail

# subset tree to just those species who have sample sizes reported, i.e. those who were tested
to_drop <- tree3 %>% filter(is.na(n)) %>% pull(label)
tree5 <- drop.tip(tree4, to_drop)
data3 <- data %>% 
  select(label, everything()) %>% 
  rename(num = n)

# species with more than X sites can get a density?
d3a <- data3 %>% group_by(species) %>% filter(n_distinct(site) >= 4)
d3b <- data3 %>% # setdiff(data3, d3a) ## <- do setdiff instead to NOT show points for densities
  group_by(species) %>% 
  # create variable num2 is NA if there's only one data point for a species
  # --> those species will only get the vertical crossbar
  mutate(flag = n_distinct(site) == 1) %>% 
  ungroup %>% 
  mutate(num2 = ifelse(flag, NA, num))

# for vertical crossbar = median
d4a <- data3 %>% 
  group_by(label, species) %>% 
  summarise(Mdn = median(num)) # totalN = sum(num), sitesN = n_distinct(site)

# for cross = median (sample size by species and site)
d4b <- data3 %>% 
  group_by(label, species, site) %>% 
  summarise(Mdn_site = median(num))%>% 
  group_by(label, species) %>% 
  summarise(Mdn_site2 = median(Mdn_site))

# make NA when equal to d4$Mdn
d4 <- full_join(d4a, d4b) %>% 
  mutate(Mdn_site2 = ifelse(Mdn == Mdn_site2, NA, Mdn_site2))
Joining, by = c("label", "species")
# for vertical line in ridge plot (grand median)
# + hacky way to make horizontal grid lines for right panel only
v <- tibble(reference = c(NA, median(data3$num)), .panel = c("Tree", "xSample size"))
h <- tibble(reference = c(NA, 1:Ntip(tree5)), .panel = c("Tree", rep("xSample size", Ntip(tree5))))

# for axis labels
ax <- tibble(lab = c("Distance", "Sample size"), x = c(67.5, max(data3$num)/2), y = -.3, 
             .panel = c("Tree", "xSample size"))
# right-side viz depends on the number of sites per species:
# 1 site = vertical crossbar only
# 2+ sites = points + crossbar at median
# X+ sites = densities (currently, X = 4 just to illustrate)

# LEFT FACET
q <- ggtree(tree5, aes(col = group)) +
  # root
  geom_rootedge(rootedge = 5) +
  # tip labels
  geom_tippoint(aes(size = n), alpha = .5) +
  geom_tiplab(offset = 4, size = 3) +
  # tweak scales
  scale_color_manual(values = c("grey30", cols)) +
  scale_fill_manual(values = cols[4]) + # when all categories are taken: cols
  # display timescale at the bottom
  theme_tree2() +
  xlim_tree(135) +
  # add axis labels
  geom_text(data = ax, aes(label = lab), col = "black") +
  scale_y_continuous(limits = c(1, Ntip(tree5)), oob = function(x, ...) x) +
  coord_cartesian(clip = "off") +
  # add reference lines (these will show up on right panel of facet_plot only)
  geom_hline(data = h, aes(yintercept = reference), lwd = .2, col = "grey", alpha = .5) +
  geom_vline(data = v, aes(xintercept = reference), lwd = 1.5, col = "grey", alpha = .3) +
  # remove facet strips, expand bottom margin (to make space for x axis labels)
  theme(strip.text = element_blank(), strip.background = element_blank(),
        plot.margin = unit(c(.5, .5, 1.2, .5), "cm"))

# dirty hack: x in front of "Sample size" is to have that panel sort to the right (alphabetically) until I figure out why it doesn't just go by order. This cropped up as an issue when I added the dummy point for the x-axis expansion...

# ADD RIGHT FACET
q %>% 
  # densities for species with enough sites
  facet_plot("xSample size", d3a, geom_density_ridges, aes(x = num, group = label, fill = group), 
             alpha = .5, lwd = .3, position = position_nudge(y = .1)) %>% 
  # vertical crossbar for Mdn, for Mdn of site medians
  facet_plot("xSample size", d4, geom_crossbarh, aes(x = Mdn, xmin = Mdn, xmax = Mdn, group = label, 
             col = group), alpha = .5, width = .3) %>%
  facet_plot("xSample size", d4, geom_point, aes(x = Mdn_site2, group = label), shape = 4, size = 2, 
             stroke = 1.5, alpha = .8) %>%
  # vertical mark for individual sites
  facet_plot("xSample size", d3b, geom_jitter, aes(x = num2, group = label), shape = "|", size = 3,
             width = .1, height = 0)

ggsave("../graphs/phylo_ridge_site.png", width = 4, height = 3, scale = 2)

Session info

sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Mojave 10.14.5

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] tidytree_0.2.8  ggtree_1.16.6   treeio_1.8.2    ggstance_0.3.3  ggridges_0.5.1 
 [6] cowplot_1.0.0   gridExtra_2.3   forcats_0.4.0   stringr_1.4.0   dplyr_0.8.3    
[11] purrr_0.3.2     readr_1.3.1     tidyr_1.0.0     tibble_2.1.3    ggplot2_3.2.1  
[16] tidyverse_1.2.1

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.2         lubridate_1.7.4    ape_5.3            lattice_0.20-38    assertthat_0.2.1  
 [6] zeallot_0.1.0      digest_0.6.21      R6_2.4.0           cellranger_1.1.0   plyr_1.8.4        
[11] backports_1.1.5    evaluate_0.14      httr_1.4.1         pillar_1.4.2       rlang_0.4.0       
[16] lazyeval_0.2.2     readxl_1.3.1       rstudioapi_0.10    rmarkdown_1.16     labeling_0.3      
[21] munsell_0.5.0      broom_0.5.2        compiler_3.6.1     modelr_0.1.5       xfun_0.10         
[26] pkgconfig_2.0.3    base64enc_0.1-3    htmltools_0.4.0    tidyselect_0.2.5   viridisLite_0.3.0 
[31] crayon_1.3.4       withr_2.1.2        grid_3.6.1         nlme_3.1-141       jsonlite_1.6      
[36] gtable_0.3.0       lifecycle_0.1.0    magrittr_1.5       scales_1.0.0       cli_1.1.0         
[41] stringi_1.4.3      reshape2_1.4.3     viridis_0.5.1      xml2_1.2.2         rvcheck_0.1.5     
[46] vctrs_0.2.0        generics_0.0.2     tools_3.6.1        glue_1.3.1         hms_0.5.1         
[51] parallel_3.6.1     yaml_2.2.0         colorspace_1.4-1   BiocManager_1.30.7 rvest_0.3.4       
[56] knitr_1.25         haven_2.1.1       
LS0tCnRpdGxlOiAiUGh5bG9nZW5ldGljIFRyZWUiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIGNzczogc3R5bGUuY3NzCiAgICB0aGVtZTogcGFwZXIKLS0tCgpMb2FkIHBhY2thZ2VzCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoZ2dyaWRnZXMpCmxpYnJhcnkoZ2dzdGFuY2UpCmxpYnJhcnkodHJlZWlvKQpsaWJyYXJ5KGdndHJlZSkKbGlicmFyeSh0aWR5dHJlZSkKYGBgCgpMb2FkIGFuZCBjb21iaW5lIGRhdGEKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpzcGVjaWVzIDwtIHJlYWRfY3N2KCIuLi9kYXRhL3NwZWNpZXNfZGF0YS5jc3YiKSAlPiUgc2VsZWN0KC1zcGVjaWVzKQpkYXRhIDwtIHJlYWRfY3N2KCIuLi9kYXRhL2RhdGEuY3N2IikgJT4lIAogIGxlZnRfam9pbihzcGVjaWVzLCBieSA9IGMoInNwZWNpZXMiID0gInNwZWNpZXNfZm9ybWF0dGVkIikpICU+JSAKICByZW5hbWUobGFiZWwgPSBzcGVjaWVzX2xhdGluKQpkYXRhMiA8LSBkYXRhICU+JSBncm91cF9ieShzcGVjaWVzLCBsYWJlbCkgJT4lIHN1bW1hcmlzZShuID0gc3VtKG4pKQpmdWxsdHJlZSA8LSByZWFkLm5leHVzKCIuLi9kYXRhL2NvbnNlbnN1c1RyZWVfMTBrVHJlZXNfMjk4UHJpbWF0ZXNfVjMubmV4IikKcmVmcyA8LSByZWFkX2NzdigiLi4vZGF0YS9yZWZfbm9kZXMuY3N2IikKYGBgCgpgYGB7cn0KIyB0dXJuIHRyZWUgaW50byB0aWR5IGRhdGFmcmFtZQp0cmVlMiA8LSBhc190aWJibGUoZnVsbHRyZWUpCgp0cmVlMyA8LSB0cmVlMiAlPiUgCiAgbGVmdF9qb2luKGRhdGEyKSAlPiUgCiAgbXV0YXRlKAogICAgaGFzTiA9IGlmZWxzZShpcy5uYShuKSwgMCwgLjUpLAogICAgaGFzTjIgPSBpZmVsc2UoaXMubmEobiksIC4xLCAuNSkpICU+JSAKICBsZWZ0X2pvaW4ocmVmcykgJT4lIAogICMgIyBhbHNvIG1lcmdlIHcgZGF0YXNoZWV0IGxpc3Rpbmcgbm9kZSwgbiBmb3IgaW5uZXIgbm9kZXMKICAjIGxlZnRfam9pbihOcywgYnkgPSAibm9kZSIpICU+JSAKICAjIG11dGF0ZShuID0gY29hbGVzY2Uobi54LCBuLnkpKSAlPiUgCiAgIyBzZWxlY3QoLW4ueCwgLW4ueSkgJT4lIAogIGdyb3VwQ2xhZGUoYyg0OTMsIDQ5NiwgNDI5LCAzMDIsIDQwOCkpICU+JSAKICBtdXRhdGUoZ3JvdXAgPSBmY3RfcmVjb2RlKGdyb3VwLCAiMiIgPSAiMSIpKQoKIyB0dXJuIGJhY2sgaW50byB0cmVlCnRyZWU0IDwtIGFzLnRyZWVkYXRhKHRyZWUzKQpgYGAKCiMgRmlndXJlIG91dCBub2RlcwoKVGhpcyBtYWtlcyBhIHJlY3Rhbmd1bGFyIGFuZCBhIGNpcmN1bGFyIHRyZWUgd2l0aCB0aGUgbm9kZSBudW1iZXJzIGRpc3BsYXllZCBmb3IgcmVmZXJlbmNlIChzYXZlZCBpbiB0aGUgYGdyYXBoc2AgZm9sZGVyKS4KCmBgYHtyfQp0cmVlMy4yIDwtIGFzLnRyZWVkYXRhKHRyZWUzKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD0yMCwgZXZhbD1GQUxTRX0KIyBkaXNwbGF5IG5vZGUgbnVtYmVycyBmb3IgcmVmZXJlbmNlCmdndHJlZSh0cmVlMy4yKSArCiAgIyB0aXAgbGFiZWxzCiAgZ2VvbV90aXBwb2ludChhZXMoc2l6ZSA9IG4pLCBjb2wgPSAic2VhZ3JlZW4iLCBhbHBoYSA9IC41KSArCiAgZ2VvbV90aXBsYWIob2Zmc2V0ID0gMSwgc2l6ZSA9IDMpICsKICAjIG5vZGUgbGFiZWxzCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG5vZGUsIHggPSBicmFuY2gpLCBzaXplID0gMiwgY29sID0gImJsdWUiLCB2anVzdCA9IC0uNSkgKwogIGV4cGFuZF9saW1pdHMoeCA9IDkwKSArCiAgIyBkaXNwbGF5IHRpbWVzY2FsZSBhdCB0aGUgYm90dG9tCiAgdGhlbWVfdHJlZTIoKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFfQpnZ3NhdmUoIi4uL2dyYXBocy9mdWxsX3RyZWVfbm9kZXMucGRmIiwgd2lkdGggPSA4LCBoZWlnaHQgPSAyMCwgc2NhbGUgPSAyKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD04LCBldmFsPUZBTFNFfQpnZ3RyZWUodHJlZTMuMiwgbGF5b3V0ID0gImNpcmN1bGFyIikgKwogIGdlb21fdGlwcG9pbnQoYWVzKHNpemUgPSBuKSwgY29sID0gInNlYWdyZWVuIiwgYWxwaGEgPSAuNSkgKwogIGdlb21fdGlwbGFiMihvZmZzZXQgPSAyLCBzaXplID0gMykgKwogIGdlb21fdGV4dDIoYWVzKGxhYmVsID0gbm9kZSksIHNpemUgPSAxLjUsIGNvbCA9ICJibHVlIikgKwogIHhsaW0oTkEsIDEwMCkKYGBgCgpgYGB7ciwgZXZhbD1GQUxTRX0KZ2dzYXZlKCIuLi9ncmFwaHMvZnVsbF90cmVlX25vZGVzX2NpcmN1bGFyLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gOCwgc2NhbGUgPSAyKQpgYGAKCiMgQ2lyY3VsYXIgdHJlZSBvZiAyOTggcHJpbWF0ZXMKCmBgYHtyfQpjb2xzIDwtIHZpcmlkaXM6OnZpcmlkaXMoNCwgZW5kID0gLjkpCmBgYAoKYGBge3J9CiMgYmFzZSBwbG90CnAgPC0gZ2d0cmVlKHRyZWU0LCBhZXMoc2l6ZSA9IGhhc04sIGFscGhhID0gaGFzTjIpLCBsYXlvdXQgPSAiY2lyY3VsYXIiKSArCiAgIyByb290CiAgZ2VvbV9yb290cG9pbnQoc2l6ZSA9IDEpICsKICAjIHRpcHMKICBnZW9tX3RpcHBvaW50KGFlcyhzaXplID0gbiksIGFscGhhID0gLjUpICsKICBnZW9tX3RpcGxhYjIoYWVzKGFscGhhID0gaGFzTiksIG9mZnNldCA9IDIsIHNpemUgPSAzKSArCiAgIyB0d2VhayBzY2FsZXMKICBzY2FsZV9hbHBoYV9jb250aW51b3VzKHJhbmdlID0gYyguMywgMSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKC41LCA4KSkgKwogICMgd2lkZW4gcGxvdHRpbmcgYXJlYQogIHhsaW0oTkEsIDEwMCkKYGBgCgpgYGB7cn0KIyBoaWdobGlnaHQgY2xhZGVzIHdpdGggYmFja2dyb3VuZCBjb2xvcnMKcDIgPC0gcCArIAogIGdlb21faGlsaWdodChub2RlID0gNDkzLCBmaWxsID0gY29sc1sxXSwgYWxwaGEgPSAuMykgKwogIGdlb21faGlsaWdodChub2RlID0gNDk2LCBmaWxsID0gY29sc1sxXSwgYWxwaGEgPSAuMykgKwogIGdlb21faGlsaWdodChub2RlID0gNDI5LCBmaWxsID0gY29sc1syXSwgYWxwaGEgPSAuMykgKwogIGdlb21faGlsaWdodChub2RlID0gMzAzLCBmaWxsID0gY29sc1szXSwgYWxwaGEgPSAuMykgKwogIGdlb21faGlsaWdodChub2RlID0gNDA4LCBmaWxsID0gY29sc1s0XSwgYWxwaGEgPSAuMykgKwogICMgcGxvdCB0cmVlIGFnYWluIHRvIGJlIG9uIHRvcCBvZiB0aGUgaGlnaGxpZ2h0cwogIGdlb21fdHJlZSgpICsKICBnZW9tX3Jvb3Rwb2ludChzaXplID0gMSkKYGBgCgpgYGB7cn0KIyBoaWdobGlnaHQgY2xhZGVzIHdpdGggYnJhbmNoIGNvbG9ycwpwMyA8LSBwICsgCiAgYWVzKGNvbCA9IGdyb3VwKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImdyYXkzMCIsIGNvbHMpKQpgYGAKCmBgYHtyfQpwbG90cyA8LSBtZ2V0KGMoInAiLCAicDIiLCAicDMiKSkKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTE4LCBmaWcuaGVpZ2h0PTZ9CmdyaWQuYXJyYW5nZShwLCBwMiwgcDMsIG5yb3cgPSAxKQpgYGAKCmBgYHtyfQojIHBuZyB3aXRoIDN4MQpnZ3NhdmUoIi4uL2dyYXBocy9waHlsb19mdWxsLnBuZyIsIGFycmFuZ2VHcm9iKGdyb2JzID0gcGxvdHMsIG5yb3cgPSAxKSwgCiAgICAgICB3aWR0aCA9IDI0LCBoZWlnaHQgPSA4LCBzY2FsZSA9IDIsIGRwaSA9IDcyKQoKIyBwZGYgd2l0aCAxIHBlciBwYWdlCmdnc2F2ZSgiLi4vZ3JhcGhzL3BoeWxvX2Z1bGwucGRmIiwgbWFycmFuZ2VHcm9iKGdyb2JzID0gcGxvdHMsIG5yb3cgPSAxLCBuY29sID0gMSksIAogICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSA4LCBzY2FsZSA9IDIsIGRwaSA9IDcyKQpgYGAKCiMgU2FtcGxlIHNpemUgaW4gZGV0YWlsCgpgYGB7cn0KIyBzdWJzZXQgdHJlZSB0byBqdXN0IHRob3NlIHNwZWNpZXMgd2hvIGhhdmUgc2FtcGxlIHNpemVzIHJlcG9ydGVkLCBpLmUuIHRob3NlIHdobyB3ZXJlIHRlc3RlZAp0b19kcm9wIDwtIHRyZWUzICU+JSBmaWx0ZXIoaXMubmEobikpICU+JSBwdWxsKGxhYmVsKQp0cmVlNSA8LSBkcm9wLnRpcCh0cmVlNCwgdG9fZHJvcCkKYGBgCgpgYGB7cn0KZGF0YTMgPC0gZGF0YSAlPiUgCiAgc2VsZWN0KGxhYmVsLCBldmVyeXRoaW5nKCkpICU+JSAKICByZW5hbWUobnVtID0gbikKCiMgc3BlY2llcyB3aXRoIG1vcmUgdGhhbiBYIHNpdGVzIGNhbiBnZXQgYSBkZW5zaXR5PwpkM2EgPC0gZGF0YTMgJT4lIGdyb3VwX2J5KHNwZWNpZXMpICU+JSBmaWx0ZXIobl9kaXN0aW5jdChzaXRlKSA+PSA0KQpkM2IgPC0gZGF0YTMgJT4lICMgc2V0ZGlmZihkYXRhMywgZDNhKSAjIyA8LSBkbyBzZXRkaWZmIGluc3RlYWQgdG8gTk9UIHNob3cgcG9pbnRzIGZvciBkZW5zaXRpZXMKICBncm91cF9ieShzcGVjaWVzKSAlPiUgCiAgIyBjcmVhdGUgdmFyaWFibGUgbnVtMiBpcyBOQSBpZiB0aGVyZSdzIG9ubHkgb25lIGRhdGEgcG9pbnQgZm9yIGEgc3BlY2llcwogICMgLS0+IHRob3NlIHNwZWNpZXMgd2lsbCBvbmx5IGdldCB0aGUgdmVydGljYWwgY3Jvc3NiYXIKICBtdXRhdGUoZmxhZyA9IG5fZGlzdGluY3Qoc2l0ZSkgPT0gMSkgJT4lIAogIHVuZ3JvdXAgJT4lIAogIG11dGF0ZShudW0yID0gaWZlbHNlKGZsYWcsIE5BLCBudW0pKQoKIyBmb3IgdmVydGljYWwgY3Jvc3NiYXIgPSBtZWRpYW4KZDRhIDwtIGRhdGEzICU+JSAKICBncm91cF9ieShsYWJlbCwgc3BlY2llcykgJT4lIAogIHN1bW1hcmlzZShNZG4gPSBtZWRpYW4obnVtKSkgIyB0b3RhbE4gPSBzdW0obnVtKSwgc2l0ZXNOID0gbl9kaXN0aW5jdChzaXRlKQoKIyBmb3IgY3Jvc3MgPSBtZWRpYW4gKHNhbXBsZSBzaXplIGJ5IHNwZWNpZXMgYW5kIHNpdGUpCmQ0YiA8LSBkYXRhMyAlPiUgCiAgZ3JvdXBfYnkobGFiZWwsIHNwZWNpZXMsIHNpdGUpICU+JSAKICBzdW1tYXJpc2UoTWRuX3NpdGUgPSBtZWRpYW4obnVtKSklPiUgCiAgZ3JvdXBfYnkobGFiZWwsIHNwZWNpZXMpICU+JSAKICBzdW1tYXJpc2UoTWRuX3NpdGUyID0gbWVkaWFuKE1kbl9zaXRlKSkKCiMgbWFrZSBOQSB3aGVuIGVxdWFsIHRvIGQ0JE1kbgpkNCA8LSBmdWxsX2pvaW4oZDRhLCBkNGIpICU+JSAKICBtdXRhdGUoTWRuX3NpdGUyID0gaWZlbHNlKE1kbiA9PSBNZG5fc2l0ZTIsIE5BLCBNZG5fc2l0ZTIpKQoKIyBmb3IgdmVydGljYWwgbGluZSBpbiByaWRnZSBwbG90IChncmFuZCBtZWRpYW4pCiMgKyBoYWNreSB3YXkgdG8gbWFrZSBob3Jpem9udGFsIGdyaWQgbGluZXMgZm9yIHJpZ2h0IHBhbmVsIG9ubHkKdiA8LSB0aWJibGUocmVmZXJlbmNlID0gYyhOQSwgbWVkaWFuKGRhdGEzJG51bSkpLCAucGFuZWwgPSBjKCJUcmVlIiwgInhTYW1wbGUgc2l6ZSIpKQpoIDwtIHRpYmJsZShyZWZlcmVuY2UgPSBjKE5BLCAxOk50aXAodHJlZTUpKSwgLnBhbmVsID0gYygiVHJlZSIsIHJlcCgieFNhbXBsZSBzaXplIiwgTnRpcCh0cmVlNSkpKSkKCiMgZm9yIGF4aXMgbGFiZWxzCmF4IDwtIHRpYmJsZShsYWIgPSBjKCJEaXN0YW5jZSIsICJTYW1wbGUgc2l6ZSIpLCB4ID0gYyg2Ny41LCBtYXgoZGF0YTMkbnVtKS8yKSwgeSA9IC0uMywgCiAgICAgICAgICAgICAucGFuZWwgPSBjKCJUcmVlIiwgInhTYW1wbGUgc2l6ZSIpKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9NCwgZmlnLmhlaWdodD0zfQojIHJpZ2h0LXNpZGUgdml6IGRlcGVuZHMgb24gdGhlIG51bWJlciBvZiBzaXRlcyBwZXIgc3BlY2llczoKIyAxIHNpdGUgPSB2ZXJ0aWNhbCBjcm9zc2JhciBvbmx5CiMgMisgc2l0ZXMgPSBwb2ludHMgKyBjcm9zc2JhciBhdCBtZWRpYW4KIyBYKyBzaXRlcyA9IGRlbnNpdGllcyAoY3VycmVudGx5LCBYID0gNCBqdXN0IHRvIGlsbHVzdHJhdGUpCgojIExFRlQgRkFDRVQKcSA8LSBnZ3RyZWUodHJlZTUsIGFlcyhjb2wgPSBncm91cCkpICsKICAjIHJvb3QKICBnZW9tX3Jvb3RlZGdlKHJvb3RlZGdlID0gNSkgKwogICMgdGlwIGxhYmVscwogIGdlb21fdGlwcG9pbnQoYWVzKHNpemUgPSBuKSwgYWxwaGEgPSAuNSkgKwogIGdlb21fdGlwbGFiKG9mZnNldCA9IDQsIHNpemUgPSAzKSArCiAgIyB0d2VhayBzY2FsZXMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZ3JleTMwIiwgY29scykpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xzWzRdKSArICMgd2hlbiBhbGwgY2F0ZWdvcmllcyBhcmUgdGFrZW46IGNvbHMKICAjIGRpc3BsYXkgdGltZXNjYWxlIGF0IHRoZSBib3R0b20KICB0aGVtZV90cmVlMigpICsKICB4bGltX3RyZWUoMTM1KSArCiAgIyBhZGQgYXhpcyBsYWJlbHMKICBnZW9tX3RleHQoZGF0YSA9IGF4LCBhZXMobGFiZWwgPSBsYWIpLCBjb2wgPSAiYmxhY2siKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMSwgTnRpcCh0cmVlNSkpLCBvb2IgPSBmdW5jdGlvbih4LCAuLi4pIHgpICsKICBjb29yZF9jYXJ0ZXNpYW4oY2xpcCA9ICJvZmYiKSArCiAgIyBhZGQgcmVmZXJlbmNlIGxpbmVzICh0aGVzZSB3aWxsIHNob3cgdXAgb24gcmlnaHQgcGFuZWwgb2YgZmFjZXRfcGxvdCBvbmx5KQogIGdlb21faGxpbmUoZGF0YSA9IGgsIGFlcyh5aW50ZXJjZXB0ID0gcmVmZXJlbmNlKSwgbHdkID0gLjIsIGNvbCA9ICJncmV5IiwgYWxwaGEgPSAuNSkgKwogIGdlb21fdmxpbmUoZGF0YSA9IHYsIGFlcyh4aW50ZXJjZXB0ID0gcmVmZXJlbmNlKSwgbHdkID0gMS41LCBjb2wgPSAiZ3JleSIsIGFscGhhID0gLjMpICsKICAjIHJlbW92ZSBmYWNldCBzdHJpcHMsIGV4cGFuZCBib3R0b20gbWFyZ2luICh0byBtYWtlIHNwYWNlIGZvciB4IGF4aXMgbGFiZWxzKQogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCksIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoLjUsIC41LCAxLjIsIC41KSwgImNtIikpCgojIGRpcnR5IGhhY2s6IHggaW4gZnJvbnQgb2YgIlNhbXBsZSBzaXplIiBpcyB0byBoYXZlIHRoYXQgcGFuZWwgc29ydCB0byB0aGUgcmlnaHQgKGFscGhhYmV0aWNhbGx5KSB1bnRpbCBJIGZpZ3VyZSBvdXQgd2h5IGl0IGRvZXNuJ3QganVzdCBnbyBieSBvcmRlci4gVGhpcyBjcm9wcGVkIHVwIGFzIGFuIGlzc3VlIHdoZW4gSSBhZGRlZCB0aGUgZHVtbXkgcG9pbnQgZm9yIHRoZSB4LWF4aXMgZXhwYW5zaW9uLi4uCgojIEFERCBSSUdIVCBGQUNFVApxICU+JSAKICAjIGRlbnNpdGllcyBmb3Igc3BlY2llcyB3aXRoIGVub3VnaCBzaXRlcwogIGZhY2V0X3Bsb3QoInhTYW1wbGUgc2l6ZSIsIGQzYSwgZ2VvbV9kZW5zaXR5X3JpZGdlcywgYWVzKHggPSBudW0sIGdyb3VwID0gbGFiZWwsIGZpbGwgPSBncm91cCksIAogICAgICAgICAgICAgYWxwaGEgPSAuNSwgbHdkID0gLjMsIHBvc2l0aW9uID0gcG9zaXRpb25fbnVkZ2UoeSA9IC4xKSkgJT4lIAogICMgdmVydGljYWwgY3Jvc3NiYXIgZm9yIE1kbiwgZm9yIE1kbiBvZiBzaXRlIG1lZGlhbnMKICBmYWNldF9wbG90KCJ4U2FtcGxlIHNpemUiLCBkNCwgZ2VvbV9jcm9zc2JhcmgsIGFlcyh4ID0gTWRuLCB4bWluID0gTWRuLCB4bWF4ID0gTWRuLCBncm91cCA9IGxhYmVsLCAKICAgICAgICAgICAgIGNvbCA9IGdyb3VwKSwgYWxwaGEgPSAuNSwgd2lkdGggPSAuMykgJT4lCiAgZmFjZXRfcGxvdCgieFNhbXBsZSBzaXplIiwgZDQsIGdlb21fcG9pbnQsIGFlcyh4ID0gTWRuX3NpdGUyLCBncm91cCA9IGxhYmVsKSwgc2hhcGUgPSA0LCBzaXplID0gMiwgCiAgICAgICAgICAgICBzdHJva2UgPSAxLjUsIGFscGhhID0gLjgpICU+JQogICMgdmVydGljYWwgbWFyayBmb3IgaW5kaXZpZHVhbCBzaXRlcwogIGZhY2V0X3Bsb3QoInhTYW1wbGUgc2l6ZSIsIGQzYiwgZ2VvbV9qaXR0ZXIsIGFlcyh4ID0gbnVtMiwgZ3JvdXAgPSBsYWJlbCksIHNoYXBlID0gInwiLCBzaXplID0gMywKICAgICAgICAgICAgIHdpZHRoID0gLjEsIGhlaWdodCA9IDApCmBgYAoKYGBge3J9Cmdnc2F2ZSgiLi4vZ3JhcGhzL3BoeWxvX3JpZGdlX3NpdGUucG5nIiwgd2lkdGggPSA0LCBoZWlnaHQgPSAzLCBzY2FsZSA9IDIpCmBgYAoKIyBTZXNzaW9uIGluZm8KCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAoK